## 作者： 修炼者 7457222@qq.com 
## 日期： 2024-12-08
## 描述： 用以生成数据库表的服务类
<%!
    import public.jygt_coder_utitls as JYGTCoderUtils
    from datetime import datetime
%><%def name="generate_service(
    table_name, 
    columns,
    indexes
)">${JYGTCoderUtils.get_desc()}
from connection.${JYGTCoderUtils.get_connection_class_name()} import mydb_pool_session, mydb_transaction, mydb_copy
from entity.${JYGTCoderUtils.get_entity_class_name(table_name)} import ${JYGTCoderUtils.get_entity_class_name(table_name)}

import re
from sqlalchemy import or_, and_
from public.jygt_coder_loger import get_logger 

logger = get_logger(__name__)

class ${JYGTCoderUtils.get_service_class_name(table_name)}:

## 生成getAll方法，支持分页
    @mydb_pool_session
    def getAll(self, page=0, per_page=10):
        """
        获取所有 ${JYGTCoderUtils.get_service_class_name(table_name)} 记录，支持分页。

        :param page: 当前页码，默认为 1。
        :param per_page: 每页记录数，默认为 10。
        :return: 包含总记录数、总页数、当前页码和记录列表的字典。
        """
        try:
            logger.info(f"{self.__class__.__name__}.getAll")
            items = self.session.query(${JYGTCoderUtils.get_entity_class_name(table_name)}
                ).limit(per_page).offset(page * per_page).all()

            total = self.session.query(${JYGTCoderUtils.get_entity_class_name(table_name)}).count()

            pages = (total + per_page - 1) // per_page

            return {
                'total': total,
                'pages': pages,
                'current_page': page,
                'items': items
            }
        except Exception as e:
            logger.error(f"Error fetching all ${JYGTCoderUtils.get_entity_class_name(table_name)} records: {e}")
            raise
    
    @mydb_pool_session
    def _get_by_filters(self, filters: list) -> list:
        """
        根据给定的过滤条件查询 ${JYGTCoderUtils.get_entity_class_name(table_name)} 记录。

        :param filters: 过滤条件列表。
        :return: 查询结果列表。
        """
        try:
            query = self.session.query(${JYGTCoderUtils.get_entity_class_name(table_name)}).filter(and_(*filters))
            return query.all()
        except Exception as e:
            logger.error(f"Error fetching ${JYGTCoderUtils.get_entity_class_name(table_name)} records with filters {filters}: {e}")
            raise

## 遍历数据库表的索引生成getByIndexName方法
## 示例：
##      getByParentId(self, f_parent_id)
##      getByParentIdAndName(self, f_parent_id, f_name)
##      getByParentIdAndNameAndCode(self, f_parent_id, f_name, f_code)
##      getByParentIdAndNameAndCodeAndType(self, f_parent_id, f_name, f_code, f_type)
    % for index_name, index_info in indexes.items():
    @mydb_pool_session
    def getBy${JYGTCoderUtils.snake_to_camel_big(index_name)}(self, ${', '.join(index_info['columns'])}):
        """
        根据 表${table_name}索引 ${index_name}  获取记录。

        输入参数：
            % for column in index_info['columns']:
                ${column}
            % endfor
        
        输出参数：
            % if index_info['unique']:
                ${JYGTCoderUtils.get_entity_class_name(table_name)}对象或 None
            % else:
                ${JYGTCoderUtils.get_entity_class_name(table_name)}列表或空
            % endif
        """
        
        logger.info(f"{self.__class__.__name__}.getBy${JYGTCoderUtils.snake_to_camel_big(index_name)}")
        
        filters = [
            % for column in index_info['columns']:
                ${JYGTCoderUtils.get_entity_class_name(table_name)}.${column} == ${column},
            % endfor
            1==1
        ]

        % if index_info['unique']:
        results = self._get_by_filters(filters)
        return results[0] if results else None
        % else:
        return self._get_by_filters(filters)
        % endif
    % endfor
## 生成Replace方法，替换一组数据，当数据存在时更新，当数据不存在时增加
    @mydb_pool_session
    @mydb_transaction
    def replace(self, records):
        """
        批量替换数据，当数据存在时更新，当数据不存在时增加。

        :param records: 要替换的数据列表。
        :return: 替换后的数据列表。
        """
        if not isinstance(records, list):
            records = [records]
        
        requests = []
        
        for record in records:
            obj = ${JYGTCoderUtils.get_entity_class_name(table_name)}(**record)

            % if JYGTCoderUtils.get_primary_from_indexes(indexes):            
            if record.get('${JYGTCoderUtils.get_primary_from_indexes(indexes)}'):
                objOld = self.getBy${JYGTCoderUtils.snake_to_camel_big('PRIMARY')}(${JYGTCoderUtils.get_primary_from_indexes(indexes)}=record['${JYGTCoderUtils.get_primary_from_indexes(indexes)}'])
                if objOld is None:
                    self.session.add(obj)
                    requests.append(obj)
                else:
                    mydb_copy(obj, objOld)
                    self.session.merge(objOld)
                    requests.append(objOld)
            else:
                self.session.add(obj)
                requests.append(obj)
            % else:
            self.session.add(obj)
            requests.append(obj)
            % endif        
        return requests
## 生成Add方法，增加一组数据，当数据存在则丢弃
    @mydb_pool_session
    @mydb_transaction
    def add(self, records):
        """
        批量增加数据，当数据不存在时增加。

        :param records: 要增加的数据列表。
        :return: 增加后的数据列表。
        """
        if not isinstance(records, list):
            records = [records]
        
        requests = []
        
        for record in records:
            obj = ${JYGTCoderUtils.get_entity_class_name(table_name)}(**record)

            % if JYGTCoderUtils.get_primary_from_indexes(indexes):            
            if record.get('${JYGTCoderUtils.get_primary_from_indexes(indexes)}'):
                objOld = self.getBy${JYGTCoderUtils.snake_to_camel_big('PRIMARY')}(${JYGTCoderUtils.get_primary_from_indexes(indexes)}=record['${JYGTCoderUtils.get_primary_from_indexes(indexes)}'])
                if objOld is None:
                    self.session.add(obj)
                    requests.append(obj)
            else:
                self.session.add(obj)
                requests.append(obj)
            % else:
            self.session.add(obj)
            requests.append(obj)
            % endif        
        return requests
## 生成Update方法，修改一组数据，当数据不存在则丢弃
    @mydb_pool_session
    @mydb_transaction
    def update(self, records):
        """
        批量修改数据，当数据存在时修改。

        :param records: 要修改的数据列表。
        :return: 修改后的数据列表。
        """
        if not isinstance(records, list):
            records = [records]
        
        requests = []
        
        for record in records:
            obj = ${JYGTCoderUtils.get_entity_class_name(table_name)}(**record)

            % if JYGTCoderUtils.get_primary_from_indexes(indexes):            
            if record.get('${JYGTCoderUtils.get_primary_from_indexes(indexes)}'):
                objOld = self.getBy${JYGTCoderUtils.snake_to_camel_big('PRIMARY')}(${JYGTCoderUtils.get_primary_from_indexes(indexes)}=record['${JYGTCoderUtils.get_primary_from_indexes(indexes)}'])
                if objOld :
                    mydb_copy(obj, objOld)
                    self.session.merge(objOld)
                    requests.append(objOld)            
            % endif        
        return requests
## 生成支持按照主键删除的方法，支持单值和列表删除
    % if any(index_name == 'PRIMARY' for index_name, index_info in indexes.items()):
        % for index_name, index_info in indexes.items():
            % if index_name == 'PRIMARY':
    @mydb_pool_session
    def delete(self, ${f"{index_info['columns'][0]}s"}):
        """
        删除指定主键集合的记录。

        输入参数：
            单值 ${f"{index_info['columns'][0]}"}
            集合 [${f"{index_info['columns'][0]}"},...]
        
        输出参数：
            删除的实体对象列表 [${JYGTCoderUtils.get_entity_class_name(table_name)}]
        """
        if not isinstance(${f"{index_info['columns'][0]}s"}, list):
            ${f"{index_info['columns'][0]}s"} = [${f"{index_info['columns'][0]}s"}]
        
        deleted_items = []
        for ${f"{index_info['columns'][0]}"} in ${f"{index_info['columns'][0]}s"}:
            try:
                oldRecord = self.getBy${JYGTCoderUtils.snake_to_camel_big(index_name)}(${f"{index_info['columns'][0]}"}=${f"{index_info['columns'][0]}"})
                if oldRecord is None:
                    continue

                self.session.delete(oldRecord)
                deleted_items.append(oldRecord)
            
            except Exception as exp:
                logger.error(exp)
                self.session.rollback()
        
        self.session.commit()
        return deleted_items
            % endif
        % endfor
    % endif
</%def>${generate_service(table_name, columns, indexes)}